/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "OpenSLES.h"
#include "OpenSLES_OpenHarmony.h"
#include "OpenSLES_Platform.h"
#include <iostream>
#include "pcm2wav.h"
#include <unistd.h>
#include "ohoslog/ohos_log.h"
#include "audio_opensles_test.h"


static void BuqqerQueueCallback (SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size);

static void PlayerStart (SLPlayItf playItf, SLOHBufferQueueItf bufferQueueItf, FILE *wavFile);

static void PlayerStop (SLPlayItf playItf, SLOHBufferQueueItf bufferQueueItf);

static void OpenSlTest();

static void OpenSlTestConcurrent();

FILE *wavFile_ = nullptr;
FILE *wavFile1_ = nullptr;
FILE *wavFile2_ = nullptr;
wav_hdr wavHeader_;
wav_hdr wavHeader1_;
wav_hdr wavHeader2_;
SLObjectItf engineObject = nullptr;
SLObjectItf outputMixObject = nullptr;
SLPlayItf playItf;
SLPlayItf playItf1;
SLPlayItf playItf2;
SLVolumeItf volumeItf1;
SLVolumeItf volumeItf2;
SLOHBufferQueueItf bufferQueueItf;
SLOHBufferQueueItf bufferQueueItf1;
SLOHBufferQueueItf bufferQueueItf2;
SLObjectItf pcmPlayerObject = nullptr;
SLObjectItf pcmPlayerObject1 = nullptr;
SLObjectItf pcmPlayerObject2 = nullptr;

int playwav(){
    size_t headerSize = sizeof(wav_hdr);
    char *inputPath = "/data/storage/el2/base/haps/entry/cache/test.wav";
    char path[PATH_MAX + 1] = {0x00};
    LOGI("playwav start");
    if ((strlen(inputPath) > PATH_MAX) || (realpath(inputPath, path) == nullptr)) {
        LOGI("Invalid path");
        return -1;
    }
    wavFile_ = fopen(path, "rb");
    LOGI("playwav fopen");
    if (wavFile_ == nullptr) {
        LOGI("AudioRendererTest: Unable to open wave file");
        return -1;
    }
    fseek(wavFile_,0,SEEK_END);
    //获取文件长度
    long length=ftell(wavFile_);
    rewind(wavFile_);
    LOGI("player--playwav ftell:%d",length);

    fread(&wavHeader_, 1, headerSize, wavFile_);
    LOGI("playwav fread");

    OpenSlTest();
    LOGI("playwav while");

    //     while (!feof(wavFile_)) {
    //         sleep(1);
    //     }
    //     PlayerStop(playItf, bufferQueueItf);
    //     (*pcmPlayerObject)->Destroy(pcmPlayerObject);

    return 0;
}


static void OpenSlTest()
{
    LOGI("audio-->OpenSlTest");
    engineObject = nullptr;
    SLEngineItf engineEngine = nullptr;
    SLresult result;
    result = slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
    result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
    result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);

    outputMixObject = nullptr;
    result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, nullptr, nullptr);
    (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);

    SLDataLocator_OutputMix slOutputMix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
    SLDataSink slSink = {&slOutputMix, nullptr};
    SLDataLocator_BufferQueue slBufferQueue = {
        SL_DATALOCATOR_BUFFERQUEUE,
        0
    };
    SLDataFormat_PCM pcmFormat = {
        SL_DATAFORMAT_PCM,
        wavHeader_.NumOfChan,
        wavHeader_.SamplesPerSec * 1000,
        wavHeader_.bitsPerSample,
        0,
        0,
        0
    };
    SLDataSource slSource = {&slBufferQueue, &pcmFormat};
    result = (*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject, &slSource, &slSink, 3, nullptr, nullptr);
    (*pcmPlayerObject)->Realize(pcmPlayerObject, SL_BOOLEAN_FALSE);

    (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_PLAY, &playItf);
    SLVolumeItf volumeItf;
    (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_VOLUME, &volumeItf);
    SLmillibel pLevel = 0;
    (*volumeItf)->GetVolumeLevel(volumeItf, &pLevel);

    LOGI("Player GetVolumeLevel pLevel:%d",pLevel);

    (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf);
    SLresult result1=(*bufferQueueItf)->RegisterCallback(bufferQueueItf, BuqqerQueueCallback, wavFile_);
    LOGI("Player RegisterCallback result:%d",result1);

     PlayerStart(playItf, bufferQueueItf, wavFile_);
}


static void BuqqerQueueCallback (SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size)
{
    LOGI("audio-->Player BuqqerQueueCallback");

    FILE *wavFile = (FILE *)pContext;
    if (!feof(wavFile)) {
        SLuint8 *buffer = nullptr;
        SLuint32 pSize = 0;
        LOGI("Player BuqqerQueueCallback go");
        (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, &pSize);
        LOGI("Player BuqqerQueueCallback go:%d",pSize);
        fread(buffer, 1, size, wavFile);

        SLOHBufferQueueState slState = {0};
        SLresult slRet = (*bufferQueueItf)->GetState(bufferQueueItf, &slState);

        LOGI("Player-->slState playIndex:%d",slState.index);
        LOGI("Player-->slState count:%d",slState.count);

        (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, size);
    }
    return;
}

static void PlayerStart (SLPlayItf playItf, SLOHBufferQueueItf bufferQueueItf, FILE *wavFile)
{
    LOGI("audio-->PlayerStart");
    (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING);
    if (!feof(wavFile)) {
        LOGI("PlayerStart go");
        SLuint8* buffer = nullptr;
        SLuint32 pSize = 0;
        (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, &pSize);
        LOGI("PlayerStart GetBuffer pSize:%d",pSize);
        fread(buffer, 1, pSize, wavFile);

        SLOHBufferQueueState slState = {0};
        SLresult slRet = (*bufferQueueItf)->GetState(bufferQueueItf, &slState);

        LOGI("Player-->slState playIndex:%d",slState.index);
        LOGI("Player-->slState count:%d",slState.count);

        (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, pSize);
    }
    return;
}


void PlayerPause(){
    LOGI("audio-->PlayerPause");
    SLresult result= (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PAUSED);
    LOGI("audio-->PlayerPause result:%d",result);
}

void continuePlay(){
    LOGI("audio-->continuePlay");
    (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING);
}

void stopPlay_(){
    LOGI("audio-->stopPlay_");
    (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
}




static void PlayerStop (SLPlayItf playItf, SLOHBufferQueueItf bufferQueueItf)
{
    LOGI("audio-->PlayerStop");
    (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
    return;
}




